home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / cross / ava-0.2.5.lha / ava-0.2.5 / src / Syntax.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-23  |  9.1 KB  |  273 lines

  1. /*
  2.   Syntax.C      
  3.   Assembler Syntax Analyzer
  4.   Uros Platise, July 1998
  5. */
  6.  
  7. #include <string.h>
  8. #include <stdio.h>
  9. #include "Keywords.h"
  10. #include "Segment.h"
  11. #include "Symbol.h"
  12. #include "Syntax.h"
  13. #include "Reports.h"
  14.  
  15. void TSyntax::Preprocessor(){
  16.   char buf [LX_STRLEN];
  17.   GET_TOKEN;
  18.   /* The first structure does not depend on ifdef_status */
  19.   if (lxP->type==TlxData::STRING){
  20.     if (strcmp(lxP->string,"endif")==0){
  21.       if (ifdef_stack.empty()){
  22.         throw syntax_error("There is no corresponding "
  23.                        "#ifdef/#ifndef for #endif.");}
  24.       ifdef_status=ifdef_stack.pop();return;
  25.     }    
  26.     else if (strcmp(lxP->string,"if")==0){
  27.       ifdef_stack.push(ifdef_status); ifdef_status &= symbol.ifexpr();return;}
  28.     else if (strcmp(lxP->string,"ifdef")==0){
  29.       ifdef_stack.push(ifdef_status); ifdef_status &= symbol.ifdef();return;}
  30.     else if (strcmp(lxP->string, "ifndef")==0){
  31.       ifdef_stack.push(ifdef_status); ifdef_status &= !symbol.ifdef();return;}
  32.     else if (strcmp(lxP->string, "else")==0){
  33.       if (ifdef_stack.empty()){
  34.         throw syntax_error("#else not within #ifdef statement.");}
  35.       ifdef_status = (ifdef_status^1) & ifdef_stack.top(); return;
  36.     }
  37.     /* if none is found, go to the 'second' switch */
  38.   }
  39.   if (ifdef_status==false){return;}  
  40.   switch(lxP->type){
  41.     case TlxData::THEEND:
  42.     case TlxData::NEWLINE: return;
  43.     case TlxData::STRING:
  44.       /* INCLUDE FILES ... */      
  45.       if (strcmp(lxP->string, "include")==0){
  46.         preproc.insert (preproc.FindFullPathName(Parse_FileName(buf)));}
  47.       else if (strcmp(lxP->string, "define")==0){symbol.addMacro();}
  48.       else if (strcmp(lxP->string, "arch")==0){
  49.         symbol.addMacro();              
  50.         if (firstDefine==true){
  51.       firstDefine=false;
  52.       strcpy(buf, AVA_LIB); strcat(buf, "/"); strcat(buf, AVA_ARCH);
  53.       preproc.insert(buf);
  54.     } else {
  55.       throw syntax_error("Target device was already defined.");
  56.     }
  57.       }
  58.       else if (strcmp(lxP->string, "undefine")==0){symbol.undefine();}
  59.       else if (strcmp(lxP->string, "adddir")==0){preproc.AddDir();}
  60.       else if (strcmp(lxP->string, "error")==0){
  61.         reports.FileStatus(TReports::VL_ALL);
  62.         WHILE_TOKEN{
  63.           if (lxP->type==TlxData::NEWLINE){break;}
  64.           reports.Info(TReports::VL_ALL, "%s ",lxP->string);
  65.         }
  66.         throw generic_error ("");
  67.       }
  68.       else if (strcmp(lxP->string, "print")==0){
  69.         reports.FileStatus(TReports::VL_ALL);
  70.         WHILE_TOKEN{
  71.           if (lxP->type==TlxData::NEWLINE){break;}
  72.           reports.Info(TReports::VL_ALL, "%s ",lxP->string);
  73.         }
  74.         reports.Info(TReports::VL_ALL, "\n");
  75.       }
  76.       else{ /* If none of above matched lxP->string */      
  77.         throw syntax_error ("Invalid preprocessor directive: #", lxP->string);}
  78.       break;
  79.  
  80.     default:
  81.       throw syntax_error ("Syntax error after '#' character.");
  82.   }
  83. }
  84.  
  85. char* TSyntax::Parse_FileName(char* buf){
  86.   GET_TOKEN; 
  87.   if (lxP->type!=TlxData::QSTRING /* && lxP->type!=TlxData::STRING */) {
  88.     throw syntax_error ("File name is missing after #include ...");}
  89.   strcpy(buf,lxP->string);
  90.   return buf;
  91. }
  92.  
  93. /*
  94.   Parse_GAS
  95.   General Parser for non-RPM expressions.
  96.   It uses General Argument Structure to store expression structure
  97.   and only if all arguments are known, expression is evaluated.
  98.   Otherwise, it is kept in its original parsed form.
  99. */
  100.  
  101. void TSyntax::Parse_GAS(int argNo=1){
  102.   int op,op_level=0;            /* (((... level */
  103.   gas.clear ();
  104.   do {
  105.     switch (lxP->type) {    
  106.       case TlxData::STRING:
  107.         if (gas.wasArgument()){
  108.   /* If expression is closed ( ... ) then string is not for us anymore */
  109.       if (op_level==0){goto check_expression;}
  110.       throw syntax_error(argNo,"Operator is required before ",lxP->string);
  111.     }
  112.     gas.push_arg(lxP->string);
  113.     if (HaltOnInvalid==true && lxP->macro==false){
  114.       throw syntax_error(argNo, "Not defined symbol: ", lxP->string);}
  115.         break;
  116.     
  117.       case TlxData::LVAL:        
  118.         if (gas.wasArgument()){
  119.       throw syntax_error(argNo,"Operator is required before ",lxP->string);}
  120.     gas.push_arg(lxP->string,lxP->lval);
  121.     break;
  122.     
  123.       case TlxData::CONTROL:
  124.         if (gas.wasArgument() && lxP->string[0]=='('){
  125.       throw syntax_error(argNo,"Undefined macro (or syntax "
  126.             "error) before: ",lxP->string);}
  127.     if (!gas.wasArgument() && lxP->string[0]==')'){
  128.       throw syntax_error(argNo,
  129.             "Argument is required before: ",lxP->string);
  130.         }
  131.     switch(lxP->string[0]){
  132.       case '(': op_level+=OP_PERIOD; gas.push_eqstr(lxP->string); break;
  133.       case ')': op_level-=OP_PERIOD; gas.push_eqstr(lxP->string); break;
  134.       default: goto check_expression;
  135.     }
  136.     break;
  137.     
  138.       case TlxData::MATH:
  139.         /* MAP one character operators */
  140.         if (lxP->string[1]==0){
  141.       switch(lxP->string[0]){
  142.         case '+': op=OP_PLUS; break;
  143.         case '-': op=OP_MINUS; break;
  144.         case '&': op=OP_LAND; break;
  145.         case '|': op=OP_LOR; break;
  146.         case '^': op=OP_LXOR; break;
  147.         case '*': op=OP_MUL; break;
  148.         case '/': op=OP_DIV; break;
  149.         case '<': op=OP_LE; break;
  150.         case '>': op=OP_GR; break;
  151.         default:  throw lexer_error(lxP->string[0]); break;
  152.       }
  153.     /* MAP two same character operators */
  154.     } else if (lxP->string[0]==lxP->string[1] && lxP->string[2]==0){
  155.       switch(lxP->string[0]){
  156.         case '<': op=OP_ASL; break;
  157.         case '>': op=OP_ASR; break;
  158.         case '=': op=OP_EQ; break;
  159.         default:  throw lexer_error(lxP->string[0]); break;
  160.       }
  161.     /* MAP >= and <= */
  162.     } else if (lxP->string[1]=='=' && lxP->string[2]==0){
  163.       switch(lxP->string[0]){
  164.         case '<': op=OP_LEQ; break;
  165.         case '>': op=OP_GEQ; break;
  166.         default:  throw lexer_error(lxP->string[0]); break;
  167.       }
  168.     /* if non of above ... error! */
  169.     }else{throw lexer_error(lxP->string[0]);}
  170.     
  171.         if (gas.wasOperator() || gas.wasNotDefined() && op!=OP_MINUS){
  172.       throw syntax_error(argNo,"Argument is required before ",lxP->string);}
  173.     
  174.     /* add zero to satisfy -x form */  
  175.     if (gas.wasNotDefined() && op==OP_MINUS){gas.update_argstack(0);}
  176.     
  177.     gas.push_op(op+op_level,lxP->string);
  178.         break;
  179.     
  180.       case TlxData::PREPROC:
  181.         throw lexer_error('#');
  182.         break;
  183.     
  184.       default:
  185.         goto check_expression;
  186.     }
  187.   } WHILE_TOKEN;
  188. check_expression:
  189.   if (op_level!=0||gas.wasOperator()){
  190.     throw syntax_error(argNo,"Malformed expression:", gas.eqstr);}
  191.   gas.evaluate(0);
  192. }
  193.  
  194. /*
  195.   Every sub-function within the following procedure must put back
  196.   last not used token. TSyntax::Run reads next token on
  197.   every pass. If sub-function does not leave last token,
  198.   one token is therefore skipped - and - not parsed!
  199. */
  200. void TSyntax::Run (){
  201.   WHILE_TOKEN{
  202.     try{
  203.       if (lxP->type==TlxData::PREPROC){Preprocessor();continue;}
  204.       if (ifdef_status==false){continue;}    
  205.       switch(lxP->type){
  206.         case TlxData::STRING: 
  207.           if (archp()){if (archp->is_Arch()){archp->Parse();break;}}
  208.         if (segment.parse()){break;}
  209.         if (keywords.parse()){break;}
  210.       if (archp()==NULL){
  211.         throw generic_error("Target device is not defined.");}
  212.         
  213.         case TlxData::LABEL:
  214.       if (symbol.addLabel()){break;}
  215.         throw syntax_error("Syntax error at: ",lxP->string);
  216.         
  217.         case TlxData::CONTROL: 
  218.       throw lexer_error(lxP->string[0]);
  219.       
  220.         case TlxData::NEWLINE: break;
  221.     
  222.         default: throw lexer_error(lxP->string[0]);
  223.       }
  224.     }
  225.     catch (lexer_error &x){reports.Error(x); lexer.Unroll();}
  226.     catch (syntax_error &x){reports.Error(x); lexer.Unroll();}
  227.   }
  228.   if (ifdef_stack.empty()==false){
  229.     throw generic_error("Program is not correctly terminated:"
  230.                         " #if(n)def/#endif count missmatch.");}
  231.  
  232.   if (archp()==NULL){throw generic_error("Device was not specified.");}
  233. }
  234.  
  235.  
  236. /*
  237.   Some Implementation of the GAS Class is found below ...
  238. */
  239.  
  240. int TGAS::OP_LEVEL [OP_PERIOD] = {0, 2,2, 3,3,3,3,3, 4,4, 1,1,1,1,1};
  241.  
  242. #define OP_CMP(a)    (OP_LEVEL[a%OP_PERIOD] + OP_PERIOD*(a/OP_PERIOD))
  243.  
  244. void TGAS::evaluate(int new_op){
  245.   unsigned int op_cmp = OP_CMP(new_op);
  246.   int op;
  247.   long tmp;
  248.   if (status==CannotSolve){return;}        /* symbols are present */
  249.   while(op_cmp <= OP_CMP(GOS[oi-1]) && oi>0){
  250.     op=pop_op()%OP_PERIOD;    
  251.     switch(op){
  252.       case OP_PLUS: update_argstack(pop_arg()+pop_arg()); break;
  253.       case OP_MINUS: update_argstack(-pop_arg()+pop_arg()); break;
  254.       case OP_LAND: update_argstack(pop_arg()&pop_arg()); break;
  255.       case OP_LOR: update_argstack(pop_arg()|pop_arg()); break;
  256.       case OP_LXOR: update_argstack(pop_arg()^pop_arg()); break;      
  257.       case OP_MUL: update_argstack(pop_arg()*pop_arg()); break;
  258.       case OP_DIV: tmp=pop_arg(); update_argstack(pop_arg()/tmp); break;
  259.       case OP_ASL: tmp=pop_arg(); update_argstack(pop_arg()<<tmp); break;
  260.       case OP_ASR: tmp=pop_arg(); update_argstack(pop_arg()>>tmp); break;
  261.       case OP_LE: update_argstack((-pop_arg()+pop_arg()) < 0); break;
  262.       case OP_GR: update_argstack((-pop_arg()+pop_arg()) > 0); break;
  263.       case OP_EQ: update_argstack((-pop_arg()+pop_arg()) == 0); break;
  264.       case OP_LEQ: update_argstack((-pop_arg()+pop_arg()) <= 0); break;
  265.       case OP_GEQ: update_argstack((-pop_arg()+pop_arg()) >= 0); break;
  266.       default: 
  267.         throw generic_error("GAS: Not yet supported operation."); break;
  268.     }
  269.   }
  270.   if(oi==0){status=Solved;}
  271. }
  272.  
  273.